![]() |
![]() |
|
Eine Objektvariable verweist auf einen Speicherbereich. Man sagt auch, dass eine Objektvariable ein Objekt referenziert, und spricht bei einer Objektvariablen von einer Objektreferenz oder einfach nur von einer Referenz. Tatsächlich ist unter einer Referenz ein Zeiger auf die Startadresse eines Speicherbereichs zu verstehen, der alle Zustandsdaten – das sind die Eigenschaften, die das Objekt von einem anderen Objekt desselben Typs unterscheidet – beschreibt. Variablen, die auf ein Objekt verweisen, werden auch als Referenztypen bezeichnet. Im Gegensatz dazu kennt .NET auch die Wertetypen wie beispielsweise Int32 (C#-Alias = int) oder Int64 (C#-Alias = long). Bei der Deklaration der Objektvariablen meinKreis wird der für das Objekt erforderliche Speicher reserviert, aber ein konkretes Objekt mit einer Zustandsausprägung durch Eigenschaften existiert schlichtweg noch nicht – die Objektvariable ist noch nicht initialisiert. Zur Initialisierung einer Objektvariablen bieten sich zwei gleichwertige Alternativen an:
Circle meinKreis; meinKreis = new Circle();
Beide weisen ein gemeinsames Merkmal auf: den Operator new, der für die Konkretisierung eines Objekts verantwortlich ist. Erst mit new beginnt der Lebenslauf eines Objekts, denn nun wird der Konstruktor der Klasse aufgerufen – in diesem Fall der parameterlose Standardkonstruktor. Sie können in einer Anweisung auch mehrere Objektvariablen desselben Typs deklarieren. Dazu werden die Objektvariablen hintereinander geschrieben und durch ein Komma voneinander getrennt:
Auch die folgende Anweisung erlaubt der C#-Compiler:
Allerdings wird nur die zuletzt angegebene Objektvariable meinKreis3 initialisiert. meinKreis1 und meinKreis2 gelten nur als deklariert und müssen zu einem späteren Zeitpunkt noch mit
initialisiert werden. 4.2.2 Zugriffsmodifizierer einer Klasse
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Modifizierer | Beschreibung |
| public | Die Instanziierbarkeit einer öffentlichen Klasse unterliegt keinerlei Beschränkungen. Die Klasse kann dann aus jeder beliebigen Anwendung heraus instanziiert werden. |
| internal | Beabsichtigen Sie, die Sichtbarkeit einer Klasse auf die Anwendung zu beschränken, in der die Klasse definiert ist, müssen Sie die Klasse internal deklarieren. Aus einer anderen Anwendung heraus kann dann auch kein Objekt dieser Klasse erzeugt werden. |
Die Angabe des Zugriffsmodifizierers ist optional. Verzichten Sie darauf, gilt die Klasse als internal.
Wir wollen nun die Auswirkungen der beiden Modifizierer public und internal an einem praktischen Beispiel erleben. Dabei werden Sie gleichzeitig mit zwei neuen Aspekten der Anwendungsentwicklung unter.NET vertraut gemacht:
| mit dem Projekttyp Klassenbibliothek |
| mit dem Zugriff auf eine externe Assembly |
Eine Klassenbibliothek wird zu einer DLL-Datei kompiliert und ist somit auch nicht eigenstartfähig. Versuchen Sie dennoch, das Projekt aus der Entwicklungsumgebung heraus zu starten, erhalten Sie eine Fehlermeldung. Sie können jedoch weiterhin über das Menü Erstellen kompilieren.
a| Achtung Stellen Sie während der Entwicklungszeit fest, dass Sie sich für den falschen Projekttyp entschieden haben, können Sie diesen im Projekteigenschaftsfenster nachträglich ändern. Wählen Sie dazu in diesem Dialog die Einstellung Allgemein, und stellen Sie im Listenfeld Ausgabetyp den gewünschten Projekttyp ein. |
Der Code des folgenden Beispiels gehört zu einer Klassenbibliothek und beschreibt die Klassen ClassA, ClassB und ClassC. Klasse ClassA ist public deklariert und sollte daher auch in anderen Anwendungen sichtbar und folglich instanziierbar sein. Der Zugriffsmodifizierer von ClassB ist internal Bisher war es nur möglich, eine Klassendefinition in einer Quellcodedatei zu implementieren, während ClassC auf jeglichen Zugriffsmodifizierer verzichtet.
| // -------------------------------------------------------------- |
| // Beispiel ...\Kapitel 4\LibraryDemo\MyClassLib |
| // -------------------------------------------------------------- |
| using System; |
| namespace MyClassLib |
| { |
| public class ClassA { |
| public int PropA = 10; |
| } |
| internal class ClassB { |
| public long PropB = 20; |
| } |
| class ClassC { |
| public string str = "Hallo"; |
| } |
| } |
Nach dem Kompilieren wird die DLL-Datei im Unterverzeichnis \bin\Debug des Projektverzeichnisses gespeichert.
Eine Klassenbibliothek dient dazu, anderen Anwendungen den Zugriff auf die öffentlichen Typen (= Klassen) zu ermöglichen. Das wollen wir nun durch eine Konsolenanwendung simulieren. Dazu bieten sich zwei Alternativen an:
| Sie öffnen ein neues Projekt in der Entwicklungsumgebung. Das erste Projekt (MyClassLib) wird dabei geschlossen. |
| Sie fügen der Entwicklungsumgebung ein zweites Projekt hinzu. Das erste Projekt bleibt dabei geöffnet und kann sogar weiter bearbeitet werden. |
Die erstgenannte Methode ist sehr einfach, daher wollen wir uns der zweiten zuwenden, bei der wir zudem tiefergehende Kenntnisse zur Entwicklung komplexerer Anwendungen mit dem Visual Studio erlangen.
Bisher haben wir in der Entwicklungsumgebung immer nur mit einem Projekt gearbeitet. Das Visual Studio ermöglicht aber auch, mehrere Projekte gleichzeitig parallel zu bearbeiten. Verwaltet werden die einzelnen Projekte in einer Projektmappe, die damit die Aufgabe eines Containers innehat. Das Visual Studio generiert beim Erstellen eines neuen Projekts eine Projektmappe, die anschließend um praktisch beliebig viele, auch unterschiedliche Projekttypen erweitert werden kann. Damit erübrigt sich das mehrfache Öffnen des Visual Studios, wenn an mehreren Projekten gearbeitet werden soll. Die von einer Projektmappe verwalteten Projekte können, müssen aber nicht zwangsläufig in einem logischen Zusammenhang stehen.
Auch Projektmappen haben einen Bezeichner. Dieser wird vergeben, sobald Sie die Entwicklungsumgebung starten und ein neues Projekt erstellen. Der Standardbezeichner einer Projektmappe ist der des ersten Projekts, sollte allerdings insbesondere dann einen spezifischen Namen bekommen, wenn Sie wissen, dass Sie im Laufe der Entwicklungstätigkeit mindestens noch ein weiteres Projekt hinzufügen wollen. Im Dialog Neues Projekt können Sie die entsprechenden Einstellungen vornehmen. In Abbildung 4.5 ist zu erkennen, dass die Wahl auf ein Projekt des Typs Klassenbibliothek gefallen ist, der Bezeichner des Projekts MyClassLib und der der Projektmappe LibraryDemo lautet.

Hier klicken, um das Bild zu vergrößern
Abbildung 4.5 Der Dialog »Neues Element hinzufügen«
Um die Entwicklungsumgebung um ein weiteres Projekt zu ergänzen, müssen Sie im Projektmappen-Explorer den Knoten markieren, dessen Kontextmenü öffnen und Hinzufügen · Neues Projekt... auswählen. Es öffnet sich daraufhin ein Dialog, der alle Projekttypen zur Auswahl stellt. Wir wollen unsere oben begonnene Klassenbibliothek testen, deshalb fällt die Wahl auf Konsolenanwendung. Der Name des neuen Projekts sei LibraryTest.
Werfen wir nun einen Blick in den Projektmappen-Explorer. Das zweite Projekt ist jetzt ebenfalls eingetragen. Werden von einer Projektmappe mehrere Projekte verwaltet, kann nur eins davon beim Klicken der Schaltfläche Starten in der Symbolleiste des Visual Studios ausgeführt werden. Es ist immer das, dessen Projektbezeichner fett geschrieben ist. In der Abbildung 4.6 würde es sich demnach um das Projekt MyClassLib, also die Klassenbibliothek handeln. Die Einstellung ist nicht korrekt. Um ein anderes Projekt zum Startprojekt zu erklären, müssen Sie das Kontextmenü des entsprechenden Projekts öffnen und Als Startprojekt festlegen auswählen.

Hier klicken, um das Bild zu vergrößern
Abbildung 4.6 Projektmappen-Explorer, der zwei Projekte beherbergt
Physikalisch werden beide Projekte MyClassLib und LibraryTest als Unterordner der Projektmappe LibraryDemo gespeichert. In Letzterem sind zwei Dateien mit den Dateierweiterungen .SLN und .SUO zu finden. In der SLN-Datei sind die Daten enthalten, welche die Projektmappe definieren, in der SUO-Datei die Daten, mit denen die Entwicklungsumgebung entsprechend der ausgewählten Optionen angepasst wird.
Das Projekt LibraryTest soll dazu dienen, die Klassenbibliothek MyClassLib zu testen. Allerdings ist LibraryTest die Existenz von MyClassLib nicht bekannt, wir müssen die Klassenbibliothek zunächst bekannt geben. Dazu dient der Knoten Verweise im Projektmappen-Explorer. Im Kontextmenü dieses Knotens wählen Sie Verweis hinzufügen... Daraufhin öffnet sich der in Abbildung 4.7 gezeigte Dialog mit den Registerkarten .NET, COM, Projekte, Durchsuchen und Aktuell. Am einfachsten ist es, Projekte auszuwählen, da in dieser Registerkarte die Projekte der aktuellen Projektmappe aufgeführt sind.
| Hinweis In Visual Studio 2002/2003 war nur der Verweis auf eine DLL-Datei möglich. Mit Visual Studio 2005 können nun auch Verweise auf EXE-Dateien gelegt werden. |

Hier klicken, um das Bild zu vergrößern
Abbildung 4.7 Der Dialog »Verweis hinzufügen«
Damit sind der Testanwendung alle notwendigen Informationen bekannt, und es kann der folgende Code geschrieben werden:
| // -------------------------------------------------------------- |
| // Beispiele: ...\Kapitel 4\LibraryDemo\LibraryTest |
| // -------------------------------------------------------------- |
| namespace LibraryTest { |
| class Program { |
| static void Main(string[] args) { |
| // Instanziierung der Klasse ClassA |
| MyClassLib.ClassA obj = new MyClassLib.ClassA(); |
| // dem Feld 'PropA' einen neuen Wert zuweisen |
| obj.PropA = 4711; |
| // Ausgabe des Feldes an der Konsole |
| Console.WriteLine(obj.PropA); |
| Console.ReadLine(); |
| } |
| } |
| } |
In Main wird ein Objekt vom Typ ClassA erzeugt. ClassA ist innerhalb des Namespaces MyClassLib definiert. Namespaces dienen dazu, die Eindeutigkeit von Klassennamen zu gewährleisten. Um auf eine Klasse zuzugreifen, muss vor dem Klassenbezeichner der Namespace angegeben werden. Beide werden durch einen Punkt voneinander getrennt.
| MyClassLib.ClassA obj = new MyClassLib.ClassA(); |
Hätten wir mit
| using MyClassLib; |
den Namensbereich der Komponente vorher bekannt gegeben, hätte die Anweisung deutlich kürzer ausfallen können:
| ClassA obj = new ClassA(); |
Zu dem Thema dieses Abschnitts, der Entwicklung einer Klassenbibliothek, sind wir gelangt, weil wir uns von der Wirkungsweise der Zugriffsmodifizierer überzeugen wollten. Wir sehen die Aussagen bestätigt, wenn wir die Liste der Intellisense-Unterstützung hinter der Namespace-Angabe MyClassLib beobachten. Hier wird nur ClassA aufgeführt, jedoch weder die internal deklarierte ClassB noch ClassC, der wir explizit keinen Zugriffsmodifizierer zugestanden haben (siehe Abbildung 4.8).

Hier klicken, um das Bild zu vergrößern
Abbildung 4.8 Intellisense-Unterstützung beim Zugriff auf eine externe Komponente
Wie oben erwähnt, darf jede Quellcodedatei mehrere Klassendefinitionen enthalten. Der Projektmappen-Explorer als Tool zur Verwaltung der projektbezogenen Dateien ist nicht in der Lage, die in einer Datei enthaltenen Klassendefinitionen anzuzeigen. Diese Aufgabe übernimmt die Klassenansicht, die darüber hinaus in einer hierarchischen Struktur alle Klassenmitglieder auflistet.
Die Klassenansicht ist in zwei Teilbereiche gegliedert. Im oberen sind die Typdefinitionen aufgeführt, zu denen nicht nur eine Klasse, sondern beispielsweise auch Strukturen, Enumerationen, Schnittstellen usw. gerechnet werden. Detailinformationen zu einer markierten Typdefinition werden im unteren Teilbereich angezeigt. In Abbildung 4.9 ist die Klasse Program ausgewählt. Diese enthält nur die Methode Main, deren Definition komplett angezeigt wird.
Vollständig implementierte Klassen können eine große Anzahl unterschiedlicher Mitglieder haben. Um eine bessere Übersicht zu erhalten, können Sie die Detailanzeige auf bestimmte Member reduzieren. Dazu klicken Sie in der Symbolleiste der Klassenansicht auf die Drop-down-Schaltfläche und wählen im Pull-down-Menü nur die Elemente aus, die für Sie von Interesse sind.

Hier klicken, um das Bild zu vergrößern
Abbildung 4.9 Die »Klassenansicht«
Bisher war es nur möglich, eine Klassendefinition in einer Quellcodedatei zu implementieren. Mit der Einführung des .NET-Frameworks 2.0 wird dem Entwickler die Möglichkeit geboten, eine Klassendefinition über mehrere Dateien zu splitten. Die neue Programmiertechnik erlaubt es mehreren Entwicklern, gleichzeitig an der gleichen Klassendefinition zu arbeiten. Ein weiterer Vorteil liegt in der impliziten Verwendung partieller Klassen durch die Entwicklungsumgebung, denn durch die Aufteilung des Klassencodes auf mehrere Dateien lässt sich der automatisch generierte Code der Entwicklungsumgebung von dem Quellcode des Entwicklers sauber trennen. Damit wird potenziellen Problemen vorgebeugt. Sie werden das erkennen, wenn wir uns mit den Windows-Anwendungen weiter hinten in diesem Buch beschäftigen.
Um eine Klasse zu splitten, muss dem Projekt zumindest eine weitere Quellcodedatei hinzugefügt werden. Sie erreichen das auf zwei verschiedenen Wegen:
| Öffnen Sie das Menü Projekt der Visual Studio-Entwicklungsumgebung, und wählen Sie dann Klasse hinzufügen..., oder |
| Sie markieren im Projektmappen-Explorer das Projekt, öffnen dessen Kontextmenü und wählen ebenfalls Klasse hinzufügen... aus. |
In beiden Fällen wird eine leere Klasse vorgegeben, dessen Typbezeichner Sie so abändern, dass die Klasse in beiden Quellcodedateien gleich lautet.
Partielle Klassendefinitionen werden durch die Ergänzung des Modifizierers partial vor allen Teildefinitionen gekennzeichnet. Die Signatur muss natürlich in jeder Teildefinition identisch sein. Nehmen wir beispielsweise an, Sie möchten die Klasse ClassA auf die beiden Dateien ClassA1.cs und ClassA2.cs aufteilen. Dann müssten die Klassendefinitionen wie folgt lauten:
| // in der Quellcodedatei 'ClassA1.cs' |
| partial class ClassA { |
| public int intX; |
| ... |
| } |
| // in der Quellcodedatei 'ClassA2.cs' |
| partial class ClassA { |
| public int intY; |
| ... |
| } |
Das Aufteilen von Typdefinitionen beschränkt sich nicht nur auf Klassen. Auch Strukturen und Interfaces, die Sie später noch kennen lernen, lassen sich auf diese Weise von mehreren Entwicklern simultan codieren. Eine Einschränkung des Gebrauchs partieller Typen müssen Sie jedoch beachten: Alle Klassenfragmente müssen sich in derselben Anwendung, also derselben EXE- oder DLL-Datei befinden.
| Hinweis Weitere Regeln im Zusammenhang mit partial erfahren Sie, wenn wir uns mit den weiteren Features der objektorientierten .NET-Programmierung beschäftigen. |
| Eine Klasse ist die Bauanleitung für Objekte eines bestimmten Typs. Ein Objekt wird durch Eigenschaften und Methoden beschrieben. |
| Die Sichtbarkeit einer Klasse wird durch public und internal beschrieben. Fehlt die Angabe eines Zugriffsmodifizierers, gilt die Klasse als internal deklariert und ist nur im aktuellen Projekt bekannt. |
| Objektvariablen werden mit dem Schlüsselwort new initialisiert und haben danach einen definierten Zustand. Bei der Instanziierung mit new wird eine Erstellungsroutine aufgerufen, die als Konstruktor bezeichnet wird. |
| Klassen-, Struktur- und Interface-Definitionen können sich über mehrere Quellcodedateien verteilen. Das Schlüsselwort partial führt bei der Kompilierung die gesplitteten Definitionen zusammen. |
| << zurück |
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.